﻿<!DOCTYPE HTML>
<html lang="zh">
<head>
<title>ComObjConnect - 语法 &amp; 使用 | AutoHotkey v2</title>
<meta name="description" content="The ComObjConnect function connects a COM object's event source to the script, enabling events to be handled." />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="../static/theme.css" rel="stylesheet" type="text/css" />
<script src="../static/content.js" type="text/javascript"></script>
</head>
<body>

<h1>ComObjConnect</h1>
<p>将 COM 对象的事件源连接到脚本, 使事件能够被处理.</p>
<pre class="Syntax"><span class="func">ComObjConnect</span> ComObj <span class="optional">, PrefixOrSink</span></pre>

<h2 id="Parameters">参数</h2>
<dl>

  <dt>ComObj</dt>
  <dd>
    <p>类型: <a href="ComObject.htm">ComObject</a></p>
    <p>产生事件的对象.</p>
    <p>如果对象不支持 IConnectionPointContainer 接口, 或无法获取对象类的类型信息, 将显示一条错误信息. 可通过 <a href="Try.htm">try</a>/<a href="Catch.htm">catch</a> 禁止或处理此错误信息.</p>
    <p>如果对象支持, 使用 IProvideClassInfo 接口以接收此对象类的类型信息. 否则, ComObjConnect 尝试通过对象的 IDispatch 接口以接收类型信息, 这可能不可靠.</p>
  </dd>

  <dt>PrefixOrSink</dt>
  <dd>
      <p>类型: <a href="../Concepts.htm#strings">字符串</a>或<a href="../Concepts.htm#objects">对象</a></p>
      <p>如果省略, 则对象为 "disconnected"; 即脚本将不再接收其事件通知. 否则, 当事件发生时, 指定一个用于确定调用哪个全局函数的前缀字符串, 或者一个<a href="#event-sink">事件接收对象</a>, 为要处理的每个事件定义一个静态方法.</p>
      <p class="warning"><strong>注意:</strong> 在此模式下不支持嵌套函数, 因为名称可能在当前函数返回后解析. 要使用嵌套函数或闭包, 请将它们附加到一个对象上, 并按照下面的描述传递该对象.</p>
    </dd>

</dl>

<h2 id="Usage">用法</h2>
<p>为了有效地使用 ComObjConnect, 您必须首先在脚本中编写函数来处理任何感兴趣的事件. 这些函数或 "事件处理程序", 具有下列结构:</p>
<pre class="Syntax Short NoIndent"><i>Prefix</i><b>EventName</b>([<i>Params...</i>, ComObj])
{
    <i class="dull">... 事件处理代码 ...</i>
    return <i>ReturnValue</i>
}</pre>
<p>如果是字符串, <i>Prefix</i> 应该与 <em>PrefixOrSink</em> 参数相同; 否则, 它应该被省略. <b>EventName</b> 应该替换为函数应该处理的任何事件的名称.</p>
<p><i>Params</i> 对应于事件拥有的任何参数. 如果事件没有参数, 则应该完全忽略 <i>Params</i>. <i>ComObj</i> 是一个额外的参数, 它包含对传递给 ComObjConnect 的原始封装对象的引用, 它从未被包含在 COM 事件的文档中. "ComObj" 应该替换为在您的脚本上下文中更有意义的名称.</p>
<p>注意, 事件处理程序可能有返回值. 要返回特定的 COM 类型的值, 使用 <a href="ComValue.htm">ComValue()</a>. 例如, <code>return ComValue(0,0)</code> 返回一个 VT_EMPTY 类型的变体, 相当于从一个 JavaScript 函数返回 <code>undefined</code>(或没有返回).</p>
<p>调用 <code>ComObjConnect(yourObject, "<i>Prefix</i>")</code> 来启用事件处理.</p>
<p>调用 <code>ComObjConnect(yourObject)</code> 来断开对象(停止处理事件).</p>
<p>如果参数的数目未知, 可以使用<a href="../Functions.htm#Variadic">可变参数函数</a>.</p>

<h3 id="event-sink">事件接收</h3>
<p>如果 <em>PrefixOrSink</em> 是一个对象, 则每当引发事件时, 就会调用该对象的相应方法. 虽然对象可以动态构造, 但 <em>PrefixOrSink</em> 更典型的做法是引用一个类或类的实例. 在这种情况下, 方法的定义如上所示, 但没有 <em>Prefix</em>.</p>
<p>与对方法的任何调用一样, 方法的(通常是隐藏的) <code>this</code> 参数包含对方法调用所通过的对象的引用; 即事件接收器对象, 而不是 COM 对象. 这可用于为事件处理程序提供上下文, 或在它们之间共享值.</p>
<p>要捕获所有事件而不为每个事件定义方法, 请定义 <a href="../Objects.htm#Meta_Functions">__Call 元函数</a>.</p>
<p>如果 COM 对象释放连接, <em>ComObject</em> 会自动释放它对 <em>PrefixOrSink</em> 的引用. 例如, Internet Explorer 在退出时就会这样做. 如果脚本不保留自己对 <em>PrefixOrSink</em> 的引用, 它可以使用 <a href="../Objects.htm#Custom_NewDelete">__Delete</a> 来检测何时发生这种情况. 如果该对象由远程进程托管, 并且该进程意外终止, 则系统可能需要几分钟才能释放连接.</p>

<h2 id="Remarks">备注</h2>
<p>脚本必须保留对 <em>ComObj</em> 的引用, 否则它将自动释放, 并与其 COM 对象断开连接, 从而阻止任何进一步的事件被检测到. 没有标准的方法来检测何时不再需要连接, 所以脚本必须通过调用 ComObjConnect 手动断开连接.</p>
<p>可能需要使用 <a href="Persistent.htm">Persistent</a> 函数, 以便在脚本监听事件时保持脚本运行.</p>
<p>失败时抛出异常.</p>

<h2 id="Related">相关</h2>
<p><a href="ComObject.htm">ComObject</a>, <a href="ComObjGet.htm">ComObjGet</a>, <a href="ComObjActive.htm">ComObjActive</a>, <a href="https://learn.microsoft.com/previous-versions/ccxe1xe6(v=vs.85)">WScript.ConnectObject (Microsoft Docs)</a></p>

<h2 id="Examples">示例</h2>
<div class="ex" id="ExIE">
<p><a class="ex_number" href="#ExIE"></a> 启动 Internet Explorer 的实例, 并将事件连接到相应的前缀为 "IE_" 的脚本函数. 有关 COM 对象和下面使用的 DocumentComplete 事件的详情, 请参阅 <a href="https://learn.microsoft.com/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa752084(v=vs.85)">InternetExplorer object (Microsoft Docs)</a>.</p>
<pre>ie := ComObject("InternetExplorer.Application")

<em>; 将事件连接到相应的 "IE_" 为前缀的脚本函数.</em>
<b>ComObjConnect</b>(ie, "IE_")

ie.Visible := true  <em>; 此语句在 IE7 中无法正常执行.</em>
ie.Navigate("https://www.autohotkey.com/")
Persistent

IE_DocumentComplete(ieEventParam, &amp;url, ieFinalParam) {
    <em>; IE 传递的 url 作为 VARIANT 的引用, 因此在上面使用 &amp;url</em>
    <em>; 以便下面的代码可以自然地引用它，而不是使用 %url%.</em>
    s := ""
    if (ie != ieEventParam)
        s .= "First parameter is a new wrapper object.`n"
    if (ie == ieFinalParam)
        s .= "Final parameter is the original wrapper object.`n"
    if (<a href="ComObjValue.htm">ComObjValue</a>(ieEventParam) == ComObjValue(ieFinalParam))
        s .= "Both wrapper objects refer to the same IDispatch instance.`n"
    MsgBox s . "Finished loading " ie.Document.title " @ " url
    ie.Quit()
    ExitApp
}
</pre>
</div>

</body>
</html>